This is what BSEDs would look like, and what the results of a bootstrapping analysis would be, under the assumptions of a) a uniform size-abundance distribution (Uniform size-abundance) and b) a uniform size-energy (Uniform size-energy)distribution.

Using the Andrews LTER small mammal data for demonstration.

Load the Andrews data, generate BSED, and get summary variables:

andrews <- load_paper_data()[[1]]
head(andrews)
andrews_bsed <- andrews %>%
  add_energy_sizeclass() %>%
  make_bsed()
andrews_vars <- list(nind = nrow(andrews),
                    nsp = length(unique(andrews$individual_species_ids)),
                    min_size = min(andrews$individual_sizes),
                    max_size = max(andrews$individual_sizes),
                    nsize_classes = nrow(andrews_bsed),
                    size_classes = andrews_bsed$size_class,
                    total_energy = sum((andrews$individual_sizes)^(3/4)))

Illustrating the conditions

Uniform size-abundance

For a uniform size-abundance distribution, individuals’ sizes are uniformly distributed from the minimum to the maximum body size in the community.

For simulation, this translates as:

unif_sa_sample <- runif(n = andrews_vars$nind, min = andrews_vars$min_size, max = andrews_vars$max_size)

We use this vector of masses to generate a BSED for the simulated community:

unif_sa_bsed <- andrews %>%
  dplyr::mutate(individual_sizes = unif_sa_sample) %>% # Change measured masses to simulated masses
  add_energy_sizeclass() %>%
  make_bsed()
head(unif_sa_bsed)

To define the “true” form of the distribution, we can define a “community” with exactly one individual of every size from the minimum to the maximum in the community and generate the corresponding BSED. replicatebecs::calculate_uniform_size_abund_bsed does this.

unif_sa_calculated <- calculate_uniform_size_abund_bsed(andrews)

Uniform size-energy

For a uniform size-energy distribution, all body size classes have an equal share of the energy use in the community.

This corresponds to a steeply negative relationship between size and abundance because a) larger individuals use more energy per capita and b) the body size classes are binned in log units, so the larger body size classes have the same amount of energy divided across a broader portion of the size spectrum.

To sample:

unif_se_bsed <- andrews_bsed %>%
  dplyr::mutate(total_energy = runif(n = andrews_vars$nsize_classes, min = 0, max = andrews_vars$total_energy)) %>% # the maximum doesn't matter, because we will convert it to proportional
  dplyr::mutate(total_energy_proportional = total_energy / sum(total_energy))

To calculate:

unif_se_calculated = andrews_bsed %>%
  dplyr::mutate(total_energy_proportional = 1/andrews_vars$nsize_classes)

Bootstrap analysis

For each community, generate: - plot of real BSED, a sample from the USA sims, and the calculated USA - p value that real BSED is similar to samples - plot of real BSED, sample from the USE sims, calculated USE - p value

rm(list=ls())
communities <- load_paper_data()
communities_energy <- lapply(communities, add_energy_sizeclass)
real_bseds <- lapply(communities_energy, make_bsed)
real_bsed_plots <- lapply(real_bseds, plot_bsed)
unif_sa_bootstraps <- lapply(communities, draw_bootstrap_samples, assumption = "uniform_size_abund", nbootstraps = 10000)
pull_bsed <- function(bootstrap_results, which_one){
  if(which_one == "first") {
  this_one <- bootstrap_results$sampled_bseds[[1]]
  } else if (which_one == "calculated") {
    this_one <- bootstrap_results$calculated_bsed
  }
  return(this_one)
}
unif_sa_samples <- lapply(unif_sa_bootstraps, pull_bsed, which_one = "first")
unif_sa_samples_plots <- lapply(unif_sa_samples, plot_bsed)
unif_sa_calculated <- lapply(unif_sa_bootstraps, pull_bsed, which_one = "calculated")
unif_sa_calculated_plots <- lapply(unif_sa_calculated, plot_bsed)
unif_sa_dois <-  lapply(unif_sa_bootstraps, calculate_bootstrap_uniform_dois)
unif_sa_pvals <- lapply(unif_sa_dois, calculate_bootstrap_p)
sa_plots_list <- list()
for(i in 1:9) {
sa_plots_list[[i]] <- gridExtra::grid.arrange(real_bsed_plots[[i]], unif_sa_samples_plots[[i]], unif_sa_calculated_plots[[i]], nrow = 1)
print(names(communities)[[i]])
print(unif_sa_pvals[[i]])
invisible(sa_plots_list[[i]])
}
[1] "andrews"
[1] 0
[1] "niwot"
[1] 0
[1] "portal"
[1] 0
[1] "sev-5pgrass"
[1] 0
[1] "sev-5plarrea"
[1] 0
[1] "sev-goatdraw"
[1] 0
[1] "sev-rsgrass"
[1] 0
[1] "sev-rslarrea"
[1] 0
[1] "sev-two22"
[1] 0

rm(list=ls())
communities <- load_paper_data()
communities_energy <- lapply(communities, add_energy_sizeclass)
real_bseds <- lapply(communities_energy, make_bsed)
real_bsed_plots <- lapply(real_bseds, plot_bsed)
unif_se_bootstraps <- lapply(communities, draw_bootstrap_samples, assumption = "uniform_size_energy", nbootstraps = 10000)
pull_bsed <- function(bootstrap_results, which_one){
  if(which_one == "first") {
  this_one <- bootstrap_results$sampled_bseds[[1]]
  } else if (which_one == "calculated") {
    this_one <- bootstrap_results$calculated_bsed
  }
  return(this_one)
}
unif_se_samples <- lapply(unif_se_bootstraps, pull_bsed, which_one = "first")
unif_se_samples_plots <- lapply(unif_se_samples, plot_bsed)
unif_se_calculated <- lapply(unif_se_bootstraps, pull_bsed, which_one = "calculated")
unif_se_calculated_plots <- lapply(unif_se_calculated, plot_bsed)
unif_se_dois <-  lapply(unif_se_bootstraps, calculate_bootstrap_uniform_dois)
unif_se_pvals <- lapply(unif_se_dois, calculate_bootstrap_p)
se_plots_list <- list()
for(i in 1:9) {
se_plots_list[[i]] <- gridExtra::grid.arrange(real_bsed_plots[[i]], unif_se_samples_plots[[i]], unif_se_calculated_plots[[i]], nrow = 1)
print(names(communities)[[i]])
print(unif_se_pvals[[i]])
invisible(se_plots_list[[i]])
}
[1] "andrews"
[1] 0.0014
[1] "niwot"
[1] 0
[1] "portal"
[1] 0
[1] "sev-5pgrass"
[1] 0
[1] "sev-5plarrea"
[1] 0
[1] "sev-goatdraw"
[1] 0
[1] "sev-rsgrass"
[1] 0
[1] "sev-rslarrea"
[1] 0
[1] "sev-two22"
[1] 8e-04

LS0tCnRpdGxlOiAiQlNFRCBzY2VuYXJpb3MiCmF1dGhvcjogIlJlbmF0YSBEaWF6IgpkYXRlOiAiNS8yOC8yMDE5IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpsaWJyYXJ5KHJlcGxpY2F0ZWJlY3MpCmBgYAoKVGhpcyBpcyB3aGF0IEJTRURzIHdvdWxkIGxvb2sgbGlrZSwgYW5kIHdoYXQgdGhlIHJlc3VsdHMgb2YgYSBib290c3RyYXBwaW5nIGFuYWx5c2lzIHdvdWxkIGJlLCB1bmRlciB0aGUgYXNzdW1wdGlvbnMgb2YgYSkgYSB1bmlmb3JtIHNpemUtYWJ1bmRhbmNlIGRpc3RyaWJ1dGlvbiAoW1VuaWZvcm0gc2l6ZS1hYnVuZGFuY2VdKSBhbmQgYikgYSB1bmlmb3JtIHNpemUtZW5lcmd5IChbVW5pZm9ybSBzaXplLWVuZXJneV0pZGlzdHJpYnV0aW9uLiAKClVzaW5nIHRoZSBBbmRyZXdzIExURVIgc21hbGwgbWFtbWFsIGRhdGEgZm9yIGRlbW9uc3RyYXRpb24uCgpMb2FkIHRoZSBBbmRyZXdzIGRhdGEsIGdlbmVyYXRlIEJTRUQsIGFuZCBnZXQgc3VtbWFyeSB2YXJpYWJsZXM6CmBgYHtyIGxvYWQgYW5kcmV3c30KYW5kcmV3cyA8LSBsb2FkX3BhcGVyX2RhdGEoKVtbMV1dCmhlYWQoYW5kcmV3cykKCmFuZHJld3NfYnNlZCA8LSBhbmRyZXdzICU+JQogIGFkZF9lbmVyZ3lfc2l6ZWNsYXNzKCkgJT4lCiAgbWFrZV9ic2VkKCkKYGBgCgpgYGB7ciBhbmRyZXdzIGRlc2NyaXB0b3IgdmFyaWFibGVzfQphbmRyZXdzX3ZhcnMgPC0gbGlzdChuaW5kID0gbnJvdyhhbmRyZXdzKSwKICAgICAgICAgICAgICAgICAgICBuc3AgPSBsZW5ndGgodW5pcXVlKGFuZHJld3MkaW5kaXZpZHVhbF9zcGVjaWVzX2lkcykpLAogICAgICAgICAgICAgICAgICAgIG1pbl9zaXplID0gbWluKGFuZHJld3MkaW5kaXZpZHVhbF9zaXplcyksCiAgICAgICAgICAgICAgICAgICAgbWF4X3NpemUgPSBtYXgoYW5kcmV3cyRpbmRpdmlkdWFsX3NpemVzKSwKICAgICAgICAgICAgICAgICAgICBuc2l6ZV9jbGFzc2VzID0gbnJvdyhhbmRyZXdzX2JzZWQpLAogICAgICAgICAgICAgICAgICAgIHNpemVfY2xhc3NlcyA9IGFuZHJld3NfYnNlZCRzaXplX2NsYXNzLAogICAgICAgICAgICAgICAgICAgIHRvdGFsX2VuZXJneSA9IHN1bSgoYW5kcmV3cyRpbmRpdmlkdWFsX3NpemVzKV4oMy80KSkpCmBgYAoKIyMgSWxsdXN0cmF0aW5nIHRoZSBjb25kaXRpb25zCgojIyMgVW5pZm9ybSBzaXplLWFidW5kYW5jZQoKRm9yIGEgdW5pZm9ybSBzaXplLWFidW5kYW5jZSBkaXN0cmlidXRpb24sIGluZGl2aWR1YWxzJyBzaXplcyBhcmUgdW5pZm9ybWx5IGRpc3RyaWJ1dGVkIGZyb20gdGhlIG1pbmltdW0gdG8gdGhlIG1heGltdW0gYm9keSBzaXplIGluIHRoZSBjb21tdW5pdHkuCgpGb3Igc2ltdWxhdGlvbiwgdGhpcyB0cmFuc2xhdGVzIGFzOgoKYGBge3IgdW5pZm9ybSBzaXplIGFidW5kIHNhbXBsaW5nfQp1bmlmX3NhX3NhbXBsZSA8LSBydW5pZihuID0gYW5kcmV3c192YXJzJG5pbmQsIG1pbiA9IGFuZHJld3NfdmFycyRtaW5fc2l6ZSwgbWF4ID0gYW5kcmV3c192YXJzJG1heF9zaXplKQpgYGAKCldlIHVzZSB0aGlzIHZlY3RvciBvZiBtYXNzZXMgdG8gZ2VuZXJhdGUgYSBCU0VEIGZvciB0aGUgc2ltdWxhdGVkIGNvbW11bml0eToKCmBgYHtyIHVuaWYgc2l6ZSBhYnVuZCBic2VkfQp1bmlmX3NhX2JzZWQgPC0gYW5kcmV3cyAlPiUKICBkcGx5cjo6bXV0YXRlKGluZGl2aWR1YWxfc2l6ZXMgPSB1bmlmX3NhX3NhbXBsZSkgJT4lICMgQ2hhbmdlIG1lYXN1cmVkIG1hc3NlcyB0byBzaW11bGF0ZWQgbWFzc2VzCiAgYWRkX2VuZXJneV9zaXplY2xhc3MoKSAlPiUKICBtYWtlX2JzZWQoKQoKaGVhZCh1bmlmX3NhX2JzZWQpCmBgYAoKVG8gZGVmaW5lIHRoZSAidHJ1ZSIgZm9ybSBvZiB0aGUgZGlzdHJpYnV0aW9uLCB3ZSBjYW4gZGVmaW5lIGEgImNvbW11bml0eSIgd2l0aCBleGFjdGx5IG9uZSBpbmRpdmlkdWFsIG9mIGV2ZXJ5IHNpemUgZnJvbSB0aGUgbWluaW11bSB0byB0aGUgbWF4aW11bSBpbiB0aGUgY29tbXVuaXR5IGFuZCBnZW5lcmF0ZSB0aGUgY29ycmVzcG9uZGluZyBCU0VELiBgcmVwbGljYXRlYmVjczo6Y2FsY3VsYXRlX3VuaWZvcm1fc2l6ZV9hYnVuZF9ic2VkYCBkb2VzIHRoaXMuIAoKYGBge3IgY2FsY3VsYXRlIHVuaWYgc2l6ZSBhYnVuZCBic2VkfQp1bmlmX3NhX2NhbGN1bGF0ZWQgPC0gY2FsY3VsYXRlX3VuaWZvcm1fc2l6ZV9hYnVuZF9ic2VkKGFuZHJld3MpCmBgYAoKCmBgYHtyIHBsb3QgdW5pZiBzaXplIGFidW5kIGJzZWRzLCBmaWcud2lkdGggPSAxNSwgZmlnLmhlaWdodCA9IDUsIGVjaG8gPSBGfQphbmRyZXdzX3Bsb3QgPSBwbG90X2JzZWQoYW5kcmV3c19ic2VkLCBic2VkX25hbWUgPSAiUmVhbCBBbmRyZXdzIikKCnVuaWZfc2Ffc2FtcGxlZF9wbG90ID0gcGxvdF9ic2VkKHVuaWZfc2FfYnNlZCwgYnNlZF9uYW1lID0gIlNhbXBsZWQgdW5pZm9ybSBzaXplLWFidW5kYW5jZSIpCgp1bmlmX3NhX2NhbGNfcGxvdCA9IHBsb3RfYnNlZCh1bmlmX3NhX2NhbGN1bGF0ZWQsIGJzZWRfbmFtZSA9ICInVHJ1ZScgdW5pZm9ybSBzaXplLWFidW5kYW5jZSIpCgp1bmlmX3NhX3Bsb3RzID0gZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UoYW5kcmV3c19wbG90LCB1bmlmX3NhX3NhbXBsZWRfcGxvdCwgdW5pZl9zYV9jYWxjX3Bsb3QsIG5yb3cgPSAxKQoKaW52aXNpYmxlKHVuaWZfc2FfcGxvdHMpCgpgYGAKCgojIyMgVW5pZm9ybSBzaXplLWVuZXJneQoKRm9yIGEgdW5pZm9ybSBzaXplLWVuZXJneSBkaXN0cmlidXRpb24sIGFsbCBib2R5IHNpemUgY2xhc3NlcyBoYXZlIGFuIGVxdWFsIHNoYXJlIG9mIHRoZSBlbmVyZ3kgdXNlIGluIHRoZSBjb21tdW5pdHkuCgpUaGlzIGNvcnJlc3BvbmRzIHRvIGEgc3RlZXBseSBuZWdhdGl2ZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzaXplIGFuZCBhYnVuZGFuY2UgYmVjYXVzZSBhKSBsYXJnZXIgaW5kaXZpZHVhbHMgdXNlIG1vcmUgZW5lcmd5IHBlciBjYXBpdGEgYW5kIGIpIHRoZSBib2R5IHNpemUgY2xhc3NlcyBhcmUgYmlubmVkIGluIGxvZyB1bml0cywgc28gdGhlIGxhcmdlciBib2R5IHNpemUgY2xhc3NlcyBoYXZlIHRoZSBzYW1lIGFtb3VudCBvZiBlbmVyZ3kgZGl2aWRlZCBhY3Jvc3MgYSBicm9hZGVyIHBvcnRpb24gb2YgdGhlIHNpemUgc3BlY3RydW0uIAoKVG8gc2FtcGxlOgoKYGBge3IgdW5pZm9ybSBzaXplIGVuZXJneSBzYW1wbGV9Cgp1bmlmX3NlX2JzZWQgPC0gYW5kcmV3c19ic2VkICU+JQogIGRwbHlyOjptdXRhdGUodG90YWxfZW5lcmd5ID0gcnVuaWYobiA9IGFuZHJld3NfdmFycyRuc2l6ZV9jbGFzc2VzLCBtaW4gPSAwLCBtYXggPSBhbmRyZXdzX3ZhcnMkdG90YWxfZW5lcmd5KSkgJT4lICMgdGhlIG1heGltdW0gZG9lc24ndCBtYXR0ZXIsIGJlY2F1c2Ugd2Ugd2lsbCBjb252ZXJ0IGl0IHRvIHByb3BvcnRpb25hbAogIGRwbHlyOjptdXRhdGUodG90YWxfZW5lcmd5X3Byb3BvcnRpb25hbCA9IHRvdGFsX2VuZXJneSAvIHN1bSh0b3RhbF9lbmVyZ3kpKQoKYGBgCgoKVG8gY2FsY3VsYXRlOgoKYGBge3IgdW5pZm9ybSBzaXplIGVuZXJneSBjYWxjdWxhdGlvbn0KdW5pZl9zZV9jYWxjdWxhdGVkID0gYW5kcmV3c19ic2VkICU+JQogIGRwbHlyOjptdXRhdGUodG90YWxfZW5lcmd5X3Byb3BvcnRpb25hbCA9IDEvYW5kcmV3c192YXJzJG5zaXplX2NsYXNzZXMpCmBgYAoKCmBgYHtyIHBsb3QgdW5pZiBzaXplIGVuZXJneSBic2VkcywgZmlnLndpZHRoID0gMTUsIGZpZy5oZWlnaHQgPSA1LCBlY2hvID0gRn0KYW5kcmV3c19wbG90ID0gcGxvdF9ic2VkKGFuZHJld3NfYnNlZCwgYnNlZF9uYW1lID0gIlJlYWwgQW5kcmV3cyIpCgp1bmlmX3NlX3NhbXBsZWRfcGxvdCA9IHBsb3RfYnNlZCh1bmlmX3NlX2JzZWQsIGJzZWRfbmFtZSA9ICJTYW1wbGVkIHVuaWZvcm0gc2l6ZS1lbmVyZ3kiKQoKdW5pZl9zZV9jYWxjX3Bsb3QgPSBwbG90X2JzZWQodW5pZl9zZV9jYWxjdWxhdGVkLCBic2VkX25hbWUgPSAiJ1RydWUnIHVuaWZvcm0gc2l6ZS1lbmVyZ3kiKQoKdW5pZl9zZV9wbG90cyA9IGdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKGFuZHJld3NfcGxvdCwgdW5pZl9zZV9zYW1wbGVkX3Bsb3QsIHVuaWZfc2VfY2FsY19wbG90LCBucm93ID0gMSkKCmludmlzaWJsZSh1bmlmX3NlX3Bsb3RzKQoKYGBgCgojIyBCb290c3RyYXAgYW5hbHlzaXMKCkZvciBlYWNoIGNvbW11bml0eSwgZ2VuZXJhdGU6Ci0gcGxvdCBvZiByZWFsIEJTRUQsIGEgc2FtcGxlIGZyb20gdGhlIFVTQSBzaW1zLCBhbmQgdGhlIGNhbGN1bGF0ZWQgVVNBIAotIHAgdmFsdWUgdGhhdCByZWFsIEJTRUQgaXMgc2ltaWxhciB0byBzYW1wbGVzCi0gcGxvdCBvZiByZWFsIEJTRUQsIHNhbXBsZSBmcm9tIHRoZSBVU0Ugc2ltcywgY2FsY3VsYXRlZCBVU0UKLSBwIHZhbHVlIAoKYGBge3Igc2l6ZSBhYnVuZGFuY2UgYm9vdHN0cmFwfQpybShsaXN0PWxzKCkpCmNvbW11bml0aWVzIDwtIGxvYWRfcGFwZXJfZGF0YSgpCgpjb21tdW5pdGllc19lbmVyZ3kgPC0gbGFwcGx5KGNvbW11bml0aWVzLCBhZGRfZW5lcmd5X3NpemVjbGFzcykKCnJlYWxfYnNlZHMgPC0gbGFwcGx5KGNvbW11bml0aWVzX2VuZXJneSwgbWFrZV9ic2VkKQoKcmVhbF9ic2VkX3Bsb3RzIDwtIGxhcHBseShyZWFsX2JzZWRzLCBwbG90X2JzZWQpCgp1bmlmX3NhX2Jvb3RzdHJhcHMgPC0gbGFwcGx5KGNvbW11bml0aWVzLCBkcmF3X2Jvb3RzdHJhcF9zYW1wbGVzLCBhc3N1bXB0aW9uID0gInVuaWZvcm1fc2l6ZV9hYnVuZCIsIG5ib290c3RyYXBzID0gMTAwMDApCgpwdWxsX2JzZWQgPC0gZnVuY3Rpb24oYm9vdHN0cmFwX3Jlc3VsdHMsIHdoaWNoX29uZSl7CiAgaWYod2hpY2hfb25lID09ICJmaXJzdCIpIHsKICB0aGlzX29uZSA8LSBib290c3RyYXBfcmVzdWx0cyRzYW1wbGVkX2JzZWRzW1sxXV0KICB9IGVsc2UgaWYgKHdoaWNoX29uZSA9PSAiY2FsY3VsYXRlZCIpIHsKICAgIHRoaXNfb25lIDwtIGJvb3RzdHJhcF9yZXN1bHRzJGNhbGN1bGF0ZWRfYnNlZAogIH0KICByZXR1cm4odGhpc19vbmUpCn0KCnVuaWZfc2Ffc2FtcGxlcyA8LSBsYXBwbHkodW5pZl9zYV9ib290c3RyYXBzLCBwdWxsX2JzZWQsIHdoaWNoX29uZSA9ICJmaXJzdCIpCgp1bmlmX3NhX3NhbXBsZXNfcGxvdHMgPC0gbGFwcGx5KHVuaWZfc2Ffc2FtcGxlcywgcGxvdF9ic2VkKQoKdW5pZl9zYV9jYWxjdWxhdGVkIDwtIGxhcHBseSh1bmlmX3NhX2Jvb3RzdHJhcHMsIHB1bGxfYnNlZCwgd2hpY2hfb25lID0gImNhbGN1bGF0ZWQiKQoKdW5pZl9zYV9jYWxjdWxhdGVkX3Bsb3RzIDwtIGxhcHBseSh1bmlmX3NhX2NhbGN1bGF0ZWQsIHBsb3RfYnNlZCkKCnVuaWZfc2FfZG9pcyA8LSAgbGFwcGx5KHVuaWZfc2FfYm9vdHN0cmFwcywgY2FsY3VsYXRlX2Jvb3RzdHJhcF91bmlmb3JtX2RvaXMpCgp1bmlmX3NhX3B2YWxzIDwtIGxhcHBseSh1bmlmX3NhX2RvaXMsIGNhbGN1bGF0ZV9ib290c3RyYXBfcCkKCmBgYAoKYGBge3Igc2l6ZSBhYnVuZGFuY2UgcGxvdHMsIGZpZy53aWR0aCA9IDE1LCBmaWcuaGVpZ2h0ID0gNX0Kc2FfcGxvdHNfbGlzdCA8LSBsaXN0KCkKCmZvcihpIGluIDE6OSkgewpzYV9wbG90c19saXN0W1tpXV0gPC0gZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UocmVhbF9ic2VkX3Bsb3RzW1tpXV0sIHVuaWZfc2Ffc2FtcGxlc19wbG90c1tbaV1dLCB1bmlmX3NhX2NhbGN1bGF0ZWRfcGxvdHNbW2ldXSwgbnJvdyA9IDEpCgpwcmludChuYW1lcyhjb21tdW5pdGllcylbW2ldXSkKcHJpbnQodW5pZl9zYV9wdmFsc1tbaV1dKQppbnZpc2libGUoc2FfcGxvdHNfbGlzdFtbaV1dKQoKfQoKYGBgCgpgYGB7ciBzaXplIGVuZXJneSBib290c3RyYXB9CnJtKGxpc3Q9bHMoKSkKY29tbXVuaXRpZXMgPC0gbG9hZF9wYXBlcl9kYXRhKCkKCmNvbW11bml0aWVzX2VuZXJneSA8LSBsYXBwbHkoY29tbXVuaXRpZXMsIGFkZF9lbmVyZ3lfc2l6ZWNsYXNzKQoKcmVhbF9ic2VkcyA8LSBsYXBwbHkoY29tbXVuaXRpZXNfZW5lcmd5LCBtYWtlX2JzZWQpCgpyZWFsX2JzZWRfcGxvdHMgPC0gbGFwcGx5KHJlYWxfYnNlZHMsIHBsb3RfYnNlZCkKCnVuaWZfc2VfYm9vdHN0cmFwcyA8LSBsYXBwbHkoY29tbXVuaXRpZXMsIGRyYXdfYm9vdHN0cmFwX3NhbXBsZXMsIGFzc3VtcHRpb24gPSAidW5pZm9ybV9zaXplX2VuZXJneSIsIG5ib290c3RyYXBzID0gMTAwMDApCgpwdWxsX2JzZWQgPC0gZnVuY3Rpb24oYm9vdHN0cmFwX3Jlc3VsdHMsIHdoaWNoX29uZSl7CiAgaWYod2hpY2hfb25lID09ICJmaXJzdCIpIHsKICB0aGlzX29uZSA8LSBib290c3RyYXBfcmVzdWx0cyRzYW1wbGVkX2JzZWRzW1sxXV0KICB9IGVsc2UgaWYgKHdoaWNoX29uZSA9PSAiY2FsY3VsYXRlZCIpIHsKICAgIHRoaXNfb25lIDwtIGJvb3RzdHJhcF9yZXN1bHRzJGNhbGN1bGF0ZWRfYnNlZAogIH0KICByZXR1cm4odGhpc19vbmUpCn0KCnVuaWZfc2Vfc2FtcGxlcyA8LSBsYXBwbHkodW5pZl9zZV9ib290c3RyYXBzLCBwdWxsX2JzZWQsIHdoaWNoX29uZSA9ICJmaXJzdCIpCgp1bmlmX3NlX3NhbXBsZXNfcGxvdHMgPC0gbGFwcGx5KHVuaWZfc2Vfc2FtcGxlcywgcGxvdF9ic2VkKQoKdW5pZl9zZV9jYWxjdWxhdGVkIDwtIGxhcHBseSh1bmlmX3NlX2Jvb3RzdHJhcHMsIHB1bGxfYnNlZCwgd2hpY2hfb25lID0gImNhbGN1bGF0ZWQiKQoKdW5pZl9zZV9jYWxjdWxhdGVkX3Bsb3RzIDwtIGxhcHBseSh1bmlmX3NlX2NhbGN1bGF0ZWQsIHBsb3RfYnNlZCkKCnVuaWZfc2VfZG9pcyA8LSAgbGFwcGx5KHVuaWZfc2VfYm9vdHN0cmFwcywgY2FsY3VsYXRlX2Jvb3RzdHJhcF91bmlmb3JtX2RvaXMpCgp1bmlmX3NlX3B2YWxzIDwtIGxhcHBseSh1bmlmX3NlX2RvaXMsIGNhbGN1bGF0ZV9ib290c3RyYXBfcCkKCmBgYAoKYGBge3Igc2l6ZSBlbmVyZ3kgcGxvdHMsIGZpZy53aWR0aCA9IDE1LCBmaWcuaGVpZ2h0ID0gNX0Kc2VfcGxvdHNfbGlzdCA8LSBsaXN0KCkKCmZvcihpIGluIDE6OSkgewpzZV9wbG90c19saXN0W1tpXV0gPC0gZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UocmVhbF9ic2VkX3Bsb3RzW1tpXV0sIHVuaWZfc2Vfc2FtcGxlc19wbG90c1tbaV1dLCB1bmlmX3NlX2NhbGN1bGF0ZWRfcGxvdHNbW2ldXSwgbnJvdyA9IDEpCgpwcmludChuYW1lcyhjb21tdW5pdGllcylbW2ldXSkKcHJpbnQodW5pZl9zZV9wdmFsc1tbaV1dKQppbnZpc2libGUoc2VfcGxvdHNfbGlzdFtbaV1dKQoKfQoKYGBg